package com.thinqq.tracktask.server;

import java.util.ArrayList;
import java.util.List;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;
import javax.jdo.annotations.Element;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Key;
import com.thinqq.tracktask.server.Store.User;

/**
* An application specific Api wrapper around the {@link DatastoreService}.
* Creating a {@link Store} is relatively expensive so one should be mindful not
* to create these unnecessarily. For example, in a servlet, the Store should be
* stored as a field in the store to avoid creating it on every request.
*
*
*/
public class Store {

 public class Api {

   /**
    * The JDO persistence manager used for all calls.
    */
   private final PersistenceManager manager;

   private Api() {
     manager = factory.getPersistenceManager();
   }

   /**
    * Begin a new transaction.
    *
    * @return the transaction
    */
   public Transaction begin() {
     final Transaction tx = manager.currentTransaction();
     tx.begin();
     return tx;
   }

   /**
    * Close the connection to the data store. Clients are expected to guarantee
    * that close will be called. This will also rollback any active
    * transaction.
    */
   public void close() {
     final Transaction tx = manager.currentTransaction();
     if (tx.isActive()) {
       tx.rollback();
     }
     manager.close();
   }

   /**
    * Gets a note from the data store.
    *
    * @param key
    *          the note's key
    * @return
    */
   public User getUser(String key) {
	   //TODO: Need to remove the hardcoded user
	   User user = null;
		try{
			user = manager.getObjectById(User.class, "1001");
		}catch (Exception e) {
		}
		if(user==null){
			//add user
			user = new User("1001", "rakesh@thinqq.com", "Rakesh");
			saveUser(user);
		}
		return user;
    }

   public void saveUser(User newUser) {
	 Transaction txn = this.begin();
	 manager.makePersistent(newUser);
 	 txn.commit();
   }

   public void addTask(User user, String input) {
	   Task task = new Task(input);
	   Transaction txn = begin();
	   manager.makePersistent(task);
	   txn.commit();
	   user.addTask(task);
   }

   public List<Task> getAllTask(User user) {
	   List<Task> taskList = new ArrayList<Store.Task>();
	   for (Long taskKey : user.getTaskKeys()) {
		   taskList.add(manager.getObjectById(Task.class, taskKey));
	   }
	   return taskList;
   }
   
 }
 
 
 /**
  * An ORM object representing an Task.
  */
 @PersistenceCapable(identityType = IdentityType.APPLICATION)
 public static class Task {
	 public Task(String input) {
		 this.taskName = input;	
	 }

	 @PrimaryKey
	 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	 private Long id;

	 @Persistent
	 private String taskName;

	 public String getTaskName() {
		 return taskName;
	 }

	 public void setTaskName(String taskName) {
		 this.taskName = taskName;
	 }

	 public Long getKey() {
		 return id;
	 }

 }
 
 
 /**
  * An ORM object representing an User.
  */
 @PersistenceCapable(identityType = IdentityType.APPLICATION)
 public static class User {

	 @PrimaryKey
	 private String id;
	 
	 @Persistent
	 private String name;
	 

	 @Persistent
	 private String email;

	 @Persistent(defaultFetchGroup = "true")
	 @Element(dependent = "true")
	 private List<Long> taskKeys = new ArrayList<Long>();

	 public User(String id, String email, String name) {
		 this.name = name;
		 this.id = id;
		 setEmail(email);
	 }

	 public void addTask(Task task){
		 List<Long> newKeys = new ArrayList<Long>(taskKeys);
		 newKeys.add(task.getKey());
		 setTaskKeys(newKeys);
	 }

	 private void setTaskKeys(List<Long> newKeys) {
		 taskKeys = newKeys;
	 }

	 public String getEmail() {
		 return email;
	 }

	 public String getName() {
		 return name;
	 }

	 public void setEmail(String email) {
		 this.email = email;
	 }

	 public void setName(String name) {
		 this.name = name;
	 }

	public List<Long> getTaskKeys() {
		return taskKeys;
	}
	 
 }

 private final PersistenceManagerFactory factory;

 /**
  * Create a new Store based on a particular config.
  *
  * @param config
  */
 public Store(String config) {
   this.factory = JDOHelper.getPersistenceManagerFactory(config);
 }

 /**
  * Starts a data store session and returns an Api object to use.
  *
  * @return
  */
 public Api getApi() {
   return new Api();
 }
}
